package cn.edu.xust.api.controller;


import cn.edu.xust.Ro.MenuRo;
import cn.edu.xust.Ro.chotelRo;
import cn.edu.xust.communication.task.TaskList;
import cn.edu.xust.configuration.exception.Default200Exception;
import cn.edu.xust.configuration.exception.ErrorConstant;
import cn.edu.xust.entity.SysLogininfoEntity;
import cn.edu.xust.entity.SysRoleEntity;
import cn.edu.xust.entity.SysUserEntity;
import cn.edu.xust.entity.SysUserroleEntity;
import cn.edu.xust.service.*;
import cn.edu.xust.util.IpUtil;
import cn.edu.xust.util.JWTUtil;
import cn.edu.xust.util.R;
import cn.edu.xust.util.RedisUtil;
import cn.hutool.crypto.SecureUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import eu.bitwalker.useragentutils.Browser;
import eu.bitwalker.useragentutils.OperatingSystem;
import eu.bitwalker.useragentutils.UserAgent;
import eu.bitwalker.useragentutils.Version;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.authz.annotation.Logical;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.io.UnsupportedEncodingException;
import java.util.Date;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.stream.Collectors;


@Slf4j
@CrossOrigin(allowCredentials = "true")
@RestController
@RequestMapping("/api/user2")
public class ApiUser2Controller {



    @Autowired
    private SysRoleService sysRoleService;
    @Autowired
    private SysUserService sysUserService;
    @Autowired
    private SysMenuService sysMenuService;
    @Autowired
    private SysUserroleService sysUserroleService;
    @Autowired
    HotelService hotelService;
    @Autowired
    SysLogininfoService sysLogininfoService;
    @Autowired
    SysUserhotelService sysUserhotelService;
    @Autowired
    RedisUtil redisUtil;
    @Autowired
    TaskList taskList;

    /***
     * 登录
     */
    @PostMapping("/login")
    public R login(@RequestBody JSONObject jsonObject, HttpServletRequest request) throws UnsupportedEncodingException, Default200Exception {

        SysLogininfoEntity logininfo = new SysLogininfoEntity();
        //处理ip地址查询
        String remortIP = IpUtil.getIpAddr(request);
        String location = IpUtil.getLocationByIp(remortIP);
        UserAgent userAgent = UserAgent.parseUserAgentString(request.getHeader("User-Agent"));
        Browser browser = userAgent.getBrowser();
        OperatingSystem operatingSystem = userAgent.getOperatingSystem();
        Version browserVersion = userAgent.getBrowserVersion();
        if (browserVersion == null) {
            logininfo.setBroswer(browser.getName());
        } else {
            logininfo.setBroswer(browser.getName() + " " + browserVersion.getVersion());
        }

        //获取输入的账号密码
        String name = (String) jsonObject.get("name");
        String password = (String) jsonObject.get("pwd");

        //存储登录信息
        logininfo.setIp(remortIP);
        logininfo.setLocation(location);
        logininfo.setUname(name);
        logininfo.setCreatetime(new Date());
        logininfo.setSystemop(operatingSystem.getName());

        //检查参数是否为空
        if (StringUtils.isEmpty(name) || StringUtils.isEmpty(password)) {
            logininfo.setState("0");
            logininfo.setDescr("填写不完整");
            sysLogininfoService.save(logininfo);
            throw new Default200Exception(ErrorConstant.userpwd_not_exist);
        }

        //判断是否存在
        SysUserEntity userEntity = sysUserService.getByName(name);
        if (userEntity == null) {
            logininfo.setState("1");
            logininfo.setDescr("用户不存在");
            sysLogininfoService.save(logininfo);
            throw new Default200Exception(ErrorConstant.user_not_exist);
        }
        //判断密码是否正确
        if (!userEntity.getPassword().equals(password)) {
            logininfo.setState("2");
            logininfo.setDescr("密码错误");
            sysLogininfoService.save(logininfo);
            throw new Default200Exception(ErrorConstant.password_error);
        }
        //生成token
        logininfo.setState("3");
        logininfo.setDescr("登录成功");
        sysLogininfoService.save(logininfo);
        log.info("登录成功");
        String token = JWTUtil.createToken(userEntity);

        //查询用户角色
        List<SysUserroleEntity> sysUserroleEntities = sysUserroleService.getByUid(userEntity.getUid());
        List<Integer> roleids = sysUserroleEntities.stream().map(SysUserroleEntity::getRoleid).collect(Collectors.toList());

        //查询角色中文名称
        List<String> strings = new CopyOnWriteArrayList<>();
        List<SysRoleEntity> allrole = sysRoleService.getByRolids(roleids);
        for (SysRoleEntity role : allrole) {
            strings.add(role.getCname());
        }

        //角色标签
        userEntity.setTags(strings);


        //获取登录路由菜单
        MenuRo menuRo = sysMenuService.getrouteByNP(name, password);


        //获取酒店以及酒店中文名
        List<chotelRo> chotelRos = sysUserhotelService.getHotelListByNP(userEntity);


        String[] arr = chotelRos.stream().map(e -> e.getHotelId().toString()).toArray(String[]::new);
        userEntity.setHotelIdList(String.join(",", arr));
        return R.ok().put("token", token).put("menu", menuRo).put("user", userEntity).put("chotel", chotelRos);
    }

    @PostMapping("/del")
    @ApiOperation(value = "删除", notes = "")
    public R del(@RequestBody JSONObject jsonObject) {
        Integer id = (Integer) jsonObject.get("id");
        QueryWrapper<SysUserEntity> wap = new QueryWrapper<SysUserEntity>().eq("uid", id);
        boolean b = sysUserService.remove(wap);
        return R.ok().put("data", b);
    }

    @PostMapping("/updatenickname")
    @ApiOperation(value = "更新（简单改个昵称）", notes = "")
    @RequiresPermissions(value = {"10"}, logical = Logical.OR)
    public R updatenickname(@RequestBody JSONObject jsonObject) throws Default200Exception {
        Integer id = (Integer) jsonObject.get("id");
        String updatenickname = (String) jsonObject.get("nickname");
        SysUserEntity byId = sysUserService.getById(id);
        if (byId == null) {
            throw new Default200Exception(ErrorConstant.userpwd_not_exist);
        }
        byId.setNickname(updatenickname);
        boolean b = sysUserService.updateById(byId);
        return R.ok().put("data", b);
    }

    @PostMapping("/update")
    @ApiOperation(value = "更新（简单改个密码）", notes = "")
    @RequiresPermissions(value = {"10"}, logical = Logical.OR)
    public R update(@RequestBody JSONObject jsonObject) throws Default200Exception {
        Integer id = (Integer) jsonObject.get("id");
        String cname = jsonObject.getString("cname");
        String oldpwd = (String) jsonObject.get("oldpwd");
        String newpwd = (String) jsonObject.get("newpwd");

        SysUserEntity byId = sysUserService.getByIdNameAndPwd(id, cname, oldpwd);
        if (byId == null) {
            throw new Default200Exception(ErrorConstant.userpwd_not_exist);
        }
        boolean b = sysUserService.updatePwd(id, newpwd);

        return R.ok().put("data", b);
    }



    @PostMapping("/resetpwd")
    @ApiOperation(value = "重置密码", notes = "")
    public R resetpwd(@RequestBody JSONObject jsonObject) throws Default200Exception {
        String mobile = jsonObject.getString("mobile");
        String validcode = jsonObject.getString("validcode");
        String newpwd = jsonObject.getString("newpwd");

        //检查手机号是否存在
        SysUserEntity user = sysUserService.getByName(mobile);
        if (user == null) {
            throw new Default200Exception(ErrorConstant.user_not_exist);
        }

        //取出redis
        String key = "reset:msgcode:" + mobile;
        Object o = redisUtil.get(key);
        String code = "";
        if (o != null) {
            code = (String) o;
            if(code.equals(validcode)){
                //密码md5
                String s = SecureUtil.md5(newpwd);
                //更新密码
                sysUserService.updatePwd(user.getUid(),s);

            }else {
                log.info("验证码核对失败{}，{}",validcode,code);
                throw new Default200Exception(ErrorConstant.valid_code_err);
            }
        } else {
            log.info("验证码未发送或者已失效{}",mobile);
            throw new Default200Exception(ErrorConstant.valid_code_err);

        }
        return R.ok();
    }



}